﻿using AutoMapper;
using DDD.Application;
using DDD.EFCore;
using DotNetCore.CAP;
using GoodsModule.Domain.GoodsAggregate;
using GoodsModule.IntegrationEvents;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GoodsModule.Application.Commands
{

    public class DeductGoodsStockByOrderCommand : ICommand<bool>
    {
        public int OrderId { get; set; }
        public Dictionary<int, int> GoodsId_Quantity { get; set; }
    }

    public class DeductGoodsStockByOrderCommandHandler(
        Infrastructure.Repositories.GoodsRepository repository,
        ICapPublisher publisher,
        IMapper mapper,
        ILogger<DeductGoodsStockByOrderCommandHandler> logger)
      : ICommandHandler<DeductGoodsStockByOrderCommand, bool>
    {
        public async Task<bool> Handle(DeductGoodsStockByOrderCommand request, CancellationToken cancellationToken)
        {
            //TODO: CommandHandler能不能发集成事件，还是得通过DomianEventHandler发出,
            //GoodsDeductStockFailIntegrationEvent集成事件需要OrderId 若通过DomianEvent发出 则需要附带一个无关聚合的额外OrderId
            //goods.CheckAndDeductStock(request.Quantity, request.OrderId);
            //return goods;

            var list = await repository.GetAll().Where(e => request.GoodsId_Quantity.Select(f => f.Key).ToArray().Contains(e.Id)).ToListAsync();
            foreach (var item in request.GoodsId_Quantity)
            {
                var goods = list.FirstOrDefault(e => e.Id == item.Key);
                if (goods == null)
                {
                    //TODO: goods.NotExist(request.OrderId) 触发商品不存在领域事件 触发商品不存在集成事件
                    throw new NotImplementedException();
                }
                //var flag = goods.CheckAndDeductStock(item.Value); 在第二个商品库存不够时  第1个商品商品库存被减了  事务怎么处理
                var flag = goods.CheckStock(item.Value);
                if (flag == false)
                {
                    var msg = new GoodsDeductStockFailIntegrationEvent(request.OrderId, goods.Id);
                    await publisher.PublishAsync(nameof(GoodsDeductStockFailIntegrationEvent), msg);
                    return false;
                }
            }
            foreach (var item in request.GoodsId_Quantity)
            {
                var goods = list.FirstOrDefault(e => e.Id == item.Key);
                goods.CheckAndDeductStock(item.Value);
            }
            {
                // TODO: 该IntegrationEvent不能由领域事件发出，考虑集成事件都由CommandHandler发出
                // 这里错了 必须由DomainEventHandler发出ntegrationEvent
                var msg = new GoodsDeductStockSuccessIntegrationEvent(request.OrderId);
                await publisher.PublishAsync(nameof(GoodsDeductStockSuccessIntegrationEvent), msg);
            }
            return true;
        }
    }
}
